#include "evaluate.h"

extern int gridUnit;
extern int x_gridNum;
extern int y_gridNum;
extern int numBins;
extern ckt this_ckt;
extern double HPWL, penalty, displacement, max_displacement, targUt;
extern string directory;
extern vector<double> util_array;

/**************************************************/
/* Global Optimization(large displacement limit)  */
/*   note: include density reduction			  */
/**************************************************/




/**************************************************/
/*	Reduce density (large displacement limit)     */
/**************************************************/

void reduce_density_1(ckt & ptrckt, double T1, double T2, int threshold)
{
	tinyRow_setup(ptrckt);
	//tinyRow_statistics(ptrckt);

	int binArea = gridUnit * gridUnit;
	int extra_area;
	Candidate temp;
	// Need to clean up?
	
	for(int i = 0; i < numBins; i++)
	{
		if(util_array[i] > T1 * targUt)
		{
			extra_area = binArea * (util_array[i] - targUt);
			queue<Candidate> qu;
			// Preparation
			for(int row = 0; row < 9; row++)
			{
				int tinyRow_ID = index_translate(i, row);
				tinyRow & this_row = ptrckt.tinyRows[tinyRow_ID];
				if(this_row.isValid == false || this_row.NodeID.size() == 0)
				{
					continue; 
				}
				else
				{
					vector<int>::iterator it;
					for(it = this_row.NodeID.begin(); it != this_row.NodeID.end(); ++it)
					{
						if(ptrckt.nodes[*it].isFixed)
							continue;
						else // Calculate the optimal region for this node
						{
							temp.cur_node = & ptrckt.nodes[*it];
							temp.src_row = & this_row;
							while(!temp.dest_row.empty())
								temp.dest_row.pop();
							if(calculate_candidate_1(ptrckt, temp, T2))
								qu.push(temp);
						}
					}
				}
			}
			// Move cells out of congested region
			while(!qu.empty() && extra_area > 0)
			{
				temp = qu.front();
				qu.pop();
				while(temp.dest_row.empty() == false)
				{
					tinyRow * dest = temp.dest_row.front();
					temp.dest_row.pop();
					int best_x = insert2tinyRow(ptrckt, *(temp.cur_node), *dest, threshold);
					if(best_x != -1)
					{
						if(insert2site(ptrckt, *(temp.cur_node), *dest, best_x))
						{
							int cur_area = (temp.cur_node)->width * (temp.cur_node)->height;
							extra_area -= cur_area;
							util_array[i] -= (double)cur_area / (gridUnit * gridUnit);
							util_array[rowid2binID(dest->ID)] += (double)cur_area / (gridUnit * gridUnit);
							assert(util_array[i] >= -0.05);
							assert(util_array[rowid2binID(dest->ID)] <= 1.05);
							erase_src_node(ptrckt, *(temp.src_row), (temp.cur_node)->ID);
							break;
						}
					}
				}
			}
		}
	}
	//tinyRow_statistics(ptrckt);
}

bool calculate_candidate_1(ckt & ptrckt, Candidate & temp, double T2)
{
	// Calculate the optimal region, using median method
	node & this_node = *(temp.cur_node);
	//tinyRow & src_row = *(temp.src_row);
	if(this_node.isFixed)
		return false;

	//Assume the average pin location is at the center

	vector<double> x;
	vector<double> y;
	int OPT_lx, OPT_rx, OPT_by, OPT_ty;

	//traverse all the nets of this node
	for(int i = 0; i < this_node.pins.size(); i++)
	{
		int netID = this_node.pins[i].pin2net;
		net & this_net = ptrckt.nets[netID];
		double x_pinloc = this_node.x_coord + 0.5 * this_node.width + this_node.pins[i].x_offset;
		double y_pinloc = this_node.y_coord + 0.5 * this_node.height + this_node.pins[i].y_offset;
		
		if( (x_pinloc <= this_net.max_X) && (x_pinloc >= this_net.min_X) )
		{	// The node is within the original bounding box
			x.push_back(this_net.min_X);
			x.push_back(this_net.max_X);
		}
		else // Recalculate the bounding box
		{
			double netMaxX = ptrckt.lx;
			double netMinX = ptrckt.rx;
			for(unsigned j = 0; j < this_net.nodeIds.size(); j++)
			{
				node & cur_node = ptrckt.nodes[ ptrckt.nets[netID].nodeIds[j] ];
				double x_pinloc = cur_node.x_coord + 0.5 * cur_node.width + this_net.x_offset[j];

				if(this_net.nodeIds[j] == this_node.ID)
					continue; // Skip this node 
					
				if(j == 0)
				{
					netMaxX = netMinX = x_pinloc;
				}
				else
				{
					netMaxX = max(netMaxX, x_pinloc);
					netMinX = min(netMinX, x_pinloc);
				}
			}

			x.push_back(netMinX);
			x.push_back(netMaxX);
		}

		if( (y_pinloc <= this_net.max_Y) && (y_pinloc >= this_net.min_Y) )
		{	// The node is within the original bounding box
			y.push_back(this_net.min_Y);
			y.push_back(this_net.max_Y);
		}
		else // Recalculate the bounding box
		{
			double netMaxY = ptrckt.by;
			double netMinY = ptrckt.ty;
			for(unsigned j = 0; j < this_net.nodeIds.size(); j++)
			{
				node & cur_node = ptrckt.nodes[ ptrckt.nets[netID].nodeIds[j] ];
				double y_pinloc = cur_node.y_coord + 0.5 * cur_node.height + this_net.y_offset[j];

				if(this_net.nodeIds[j] == this_node.ID)
					continue; // Skip this node 
					
				if(j == 0)
				{
					netMaxY = netMinY = y_pinloc;
				}
				else
				{
					netMaxY = max(netMaxY, y_pinloc);
					netMinY = min(netMinY, y_pinloc);
				}
			}

			y.push_back(netMinY);
			y.push_back(netMaxY);
		}
	}
	// Calculate the median, thus deriving the optimal region of current node
	
	int num_net = this_node.pins.size();
	double opt_lx, opt_rx, opt_by, opt_ty;
	sort(x.begin(), x.end());
	sort(y.begin(), y.end());

	if(num_net == 0)
	{
		opt_lx = opt_rx = this_node.x_coord;
		opt_by = opt_ty = this_node.y_coord;
	}
	else
	{
		opt_lx = x[num_net - 1];
		opt_rx = x[num_net];
		opt_by = y[num_net - 1];
		opt_ty = y[num_net];
	}

	// Express the optimal region in terms of the left end of the node 
	OPT_lx = opt_lx - 0.5 * this_node.width;
	OPT_rx = opt_rx - 0.5 * this_node.width;
	OPT_by = opt_by - 0.5 * this_node.height;
	OPT_ty = opt_ty - 0.5 * this_node.height;
	if(OPT_lx < ptrckt.lx) OPT_lx = ptrckt.lx;
	if(OPT_rx > ptrckt.rx) OPT_rx = ptrckt.rx - 1;
	if(OPT_by < ptrckt.by) OPT_by = ptrckt.by;
	if(OPT_ty > ptrckt.ty) OPT_ty = ptrckt.ty - 1;

	assert(OPT_lx >= ptrckt.lx);
	assert(OPT_rx <= ptrckt.rx);
	assert(OPT_by >= ptrckt.by);
	assert(OPT_ty <= ptrckt.ty);

	// Select eligible tinyRows from the optimal region
	int bottomleft_ID = xy2tinyRowID(ptrckt, OPT_lx, OPT_by);
	int topleft_ID = xy2tinyRowID(ptrckt, OPT_lx, OPT_ty);
	int N_horizontal = xy2tinyRowID(ptrckt, OPT_rx, OPT_by) - bottomleft_ID;
	int srcBinID = rowid2binID(temp.src_row->ID);

	assert(bottomleft_ID >= 0 && bottomleft_ID <= 9 * numBins);
	assert(topleft_ID >= 0 && topleft_ID <= 9 * numBins);
	assert(N_horizontal <= x_gridNum);
	assert(srcBinID >= 0 && srcBinID <= numBins);


	for(int id = bottomleft_ID; id <= topleft_ID; id += x_gridNum)
	{
		int temp_id;
		for(temp_id = id; temp_id <= id + N_horizontal; temp_id++)
		{
			int binID = rowid2binID(temp_id);
			if(binID == srcBinID)
				continue;
			/* For each candidate tinyrow, we find its corresponding tinyrow. If the bin's too far away from the original position of the node, 
				we don't consider that tinyrow */
			if(max_distance(ptrckt, temp_id, this_node) > max_displacement)
				continue;
			if(ptrckt.tinyRows[temp_id].isValid && util_array[binID] < T2 * targUt)
			{
				temp.dest_row.push(& ptrckt.tinyRows[temp_id]);
			}
		}
	}

	if(temp.dest_row.size() != 0)
		return true;
	else
		return false;
}

void reduce_density_2(ckt & ptrckt, double T1, double T2, int threshold)
{
	tinyRow_setup(ptrckt);

	int binArea = gridUnit * gridUnit;
	int extra_area;
	Candidate temp;
	// Need to clean up?
	
	for(int i = 0; i < numBins; i++)
	{
		if(util_array[i] > T1 * targUt)
		{
			extra_area = binArea * (util_array[i] - targUt);
			queue<Candidate> qu;
			// Preparation
			for(int row = 0; row < 9; row++)
			{
				int tinyRow_ID = index_translate(i, row);
				tinyRow & this_row = ptrckt.tinyRows[tinyRow_ID];
				if(this_row.isValid == false || this_row.NodeID.size() == 0)
					continue; 
				else
				{
					vector<int>::iterator it;
					for(it = this_row.NodeID.begin(); it != this_row.NodeID.end(); ++it)
					{
						if(ptrckt.nodes[*it].isFixed)
							continue;
						else // Calculate the optimal region for this node
						{
							temp.cur_node = & ptrckt.nodes[*it];
							temp.src_row = & this_row;
							while(!temp.dest_row.empty())
								temp.dest_row.pop();
							if(calculate_candidate_2(ptrckt, temp, T2))
								qu.push(temp);
						}
					}
				}
			}
			// Move cells out of congested region
			while(!qu.empty() && extra_area > 0)
			{
				temp = qu.front();
				qu.pop();
				while(temp.dest_row.empty() == false)
				{
					tinyRow * dest = temp.dest_row.front();
					temp.dest_row.pop();
					int best_x = insert2tinyRow(ptrckt, *(temp.cur_node), *dest, threshold);
					if(best_x != -1)
					{
						if(insert2site(ptrckt, *(temp.cur_node), *dest, best_x));
						{
							int cur_area = (temp.cur_node)->width * (temp.cur_node)->height;
							extra_area -= cur_area;
							util_array[i] -= (double)cur_area / (gridUnit * gridUnit);
							util_array[rowid2binID(dest->ID)] += (double)cur_area / (gridUnit * gridUnit);
							assert(util_array[i] >= -0.05);
							assert(util_array[rowid2binID(dest->ID)] <= 1.05);
							erase_src_node(ptrckt, *(temp.src_row), (temp.cur_node)->ID);
							break;
						}
					}
				}
			}
		}
	}
}


bool calculate_candidate_2(ckt & ptrckt, Candidate & temp, double T2)
{
	// Calculate the optimal region, using median method
	node & this_node = *(temp.cur_node);
	//tinyRow & src_row = *(temp.src_row);
	if(this_node.isFixed)
		return false;

	//Assume the average pin location is at the center

		vector<double> x;
	vector<double> y;
	int OPT_lx, OPT_rx, OPT_by, OPT_ty;

	//traverse all the nets of this node
	for(int i = 0; i < this_node.pins.size(); i++)
	{
		int netID = this_node.pins[i].pin2net;
		net & this_net = ptrckt.nets[netID];
		double x_pinloc = this_node.x_coord + 0.5 * this_node.width + this_node.pins[i].x_offset;
		double y_pinloc = this_node.y_coord + 0.5 * this_node.height + this_node.pins[i].y_offset;
		
		if( (x_pinloc <= this_net.max_X) && (x_pinloc >= this_net.min_X) )
		{	// The node is within the original bounding box
			x.push_back(this_net.min_X);
			x.push_back(this_net.max_X);
		}
		else // Recalculate the bounding box
		{
			double netMaxX = ptrckt.lx;
			double netMinX = ptrckt.rx;
			for(unsigned j = 0; j < this_net.nodeIds.size(); j++)
			{
				node & cur_node = ptrckt.nodes[ ptrckt.nets[netID].nodeIds[j] ];
				double x_pinloc = cur_node.x_coord + 0.5 * cur_node.width + this_net.x_offset[j];

				if(this_net.nodeIds[j] == this_node.ID)
					continue; // Skip this node 
					
				if(j == 0)
				{
					netMaxX = netMinX = x_pinloc;
				}
				else
				{
					netMaxX = max(netMaxX, x_pinloc);
					netMinX = min(netMinX, x_pinloc);
				}
			}

			x.push_back(netMinX);
			x.push_back(netMaxX);
		}

		if( (y_pinloc <= this_net.max_Y) && (y_pinloc >= this_net.min_Y) )
		{	// The node is within the original bounding box
			y.push_back(this_net.min_Y);
			y.push_back(this_net.max_Y);
		}
		else // Recalculate the bounding box
		{
			double netMaxY = ptrckt.by;
			double netMinY = ptrckt.ty;
			for(unsigned j = 0; j < this_net.nodeIds.size(); j++)
			{
				node & cur_node = ptrckt.nodes[ ptrckt.nets[netID].nodeIds[j] ];
				double y_pinloc = cur_node.y_coord + 0.5 * cur_node.height + this_net.y_offset[j];

				if(this_net.nodeIds[j] == this_node.ID)
					continue; // Skip this node 
					
				if(j == 0)
				{
					netMaxY = netMinY = y_pinloc;
				}
				else
				{
					netMaxY = max(netMaxY, y_pinloc);
					netMinY = min(netMinY, y_pinloc);
				}
			}

			y.push_back(netMinY);
			y.push_back(netMaxY);
		}
	}
	// Calculate the median, thus deriving the optimal region of current node
	
	int num_net = this_node.pins.size();
	double opt_lx, opt_rx, opt_by, opt_ty;
	sort(x.begin(), x.end());
	sort(y.begin(), y.end());

	if(num_net == 0)
	{
		opt_lx = opt_rx = this_node.x_coord;
		opt_by = opt_ty = this_node.y_coord;
	}
	else
	{
		opt_lx = x[num_net - 1];
		opt_rx = x[num_net];
		opt_by = y[num_net - 1];
		opt_ty = y[num_net];
	}
	// Express the optimal region in terms of the left end of the node 
	OPT_lx = opt_lx - 0.5 * this_node.width - 81;
	OPT_rx = opt_rx - 0.5 * this_node.width + 81;
	OPT_by = opt_by - 0.5 * this_node.height - 81;
	OPT_ty = opt_ty - 0.5 * this_node.height + 81;
	if(OPT_lx < ptrckt.lx) OPT_lx = ptrckt.lx;
	if(OPT_rx > ptrckt.rx) OPT_rx = ptrckt.rx - 1;
	if(OPT_by < ptrckt.by) OPT_by = ptrckt.by;
	if(OPT_ty > ptrckt.ty) OPT_ty = ptrckt.ty - 1;

	assert(OPT_lx >= ptrckt.lx);
	assert(OPT_rx <= ptrckt.rx);
	assert(OPT_by >= ptrckt.by);
	assert(OPT_ty <= ptrckt.ty);

	// Select eligible tinyRows from the optimal region
	int bottomleft_ID = xy2tinyRowID(ptrckt, OPT_lx, OPT_by);
	int topleft_ID = xy2tinyRowID(ptrckt, OPT_lx, OPT_ty);
	int bottomright_ID = xy2tinyRowID(ptrckt, OPT_rx, OPT_by);

	assert(bottomright_ID - bottomleft_ID <= x_gridNum);
	int N_horizontal = bottomright_ID - bottomleft_ID;
	int srcBinID = rowid2binID(temp.src_row->ID);
	assert(bottomleft_ID >= 0 && bottomleft_ID < 9 * numBins);
	assert(topleft_ID >= 0 && topleft_ID < 9 * numBins);
	assert(N_horizontal <= x_gridNum);
	assert(srcBinID >= 0 && srcBinID < numBins);


	for(int id = bottomleft_ID; id <= topleft_ID; id += x_gridNum)
	{
		int temp_id;
		for(temp_id = id; temp_id <= id + N_horizontal; temp_id++)
		{
			int binID = rowid2binID(temp_id);
			if(binID == srcBinID)
				continue;
			/* For each candidate tinyrow, we find its corresponding tinyrow. If the bin's too far away from the original position of the node, 
				we don't consider that tinyrow */
			if(max_distance(ptrckt, temp_id, this_node) > max_displacement)
				continue;
			if(ptrckt.tinyRows[temp_id].isValid && util_array[binID] < T2 * targUt)
			{
				temp.dest_row.push(& ptrckt.tinyRows[temp_id]);
			}
		}
	}

	if(temp.dest_row.size() != 0)
		return true;
	else
		return false;
}

void reduce_density_3(ckt & ptrckt, double T1, double T2, int threshold)
{
	tinyRow_setup(ptrckt);

	int binArea = gridUnit * gridUnit;
	int extra_area;
	Candidate temp;
	// Need to clean up?
	
	for(int i = 0; i < numBins; i++)
	{
		if(util_array[i] > T1 * targUt)
		{
			extra_area = binArea * (util_array[i] - targUt);
			queue<Candidate> qu;
			// Preparation
			for(int row = 0; row < 9; row++)
			{
				int tinyRow_ID = index_translate(i, row);
				tinyRow & this_row = ptrckt.tinyRows[tinyRow_ID];
				if(this_row.isValid == false || this_row.NodeID.size() == 0)
					continue; 
				else
				{
					vector<int>::iterator it;
					for(it = this_row.NodeID.begin(); it != this_row.NodeID.end(); ++it)
					{
						if(ptrckt.nodes[*it].isFixed)
							continue;
						else // Calculate the optimal region for this node
						{
							temp.cur_node = & ptrckt.nodes[*it];
							temp.src_row = & this_row;
							while(!temp.dest_row.empty())
								temp.dest_row.pop();
							if(calculate_candidate_3(ptrckt, temp, T2))
								qu.push(temp);
						}
					}
				}
			}
			// Move cells out of congested region
			while(!qu.empty() && extra_area > 0)
			{
				temp = qu.front();
				qu.pop();
				while(temp.dest_row.empty() == false)
				{
					tinyRow * dest = temp.dest_row.front();
					temp.dest_row.pop();
					int best_x = insert2tinyRow(ptrckt, *(temp.cur_node), *dest, threshold);
					if(best_x != -1)
					{
						if(insert2site(ptrckt, *(temp.cur_node), *dest, best_x));
						{
							int cur_area = (temp.cur_node)->width * (temp.cur_node)->height;
							extra_area -= cur_area;
							util_array[i] -= (double)cur_area / (gridUnit * gridUnit);
							util_array[rowid2binID(dest->ID)] += (double)cur_area / (gridUnit * gridUnit);
							assert(util_array[i] >= -0.05);
							assert(util_array[rowid2binID(dest->ID)] <= 1.05);
							erase_src_node(ptrckt, *(temp.src_row), (temp.cur_node)->ID);
							break;
						}
					}
				}
			}
		}
	}
}


bool calculate_candidate_3(ckt & ptrckt, Candidate & temp, double T2)
{
	// Calculate the optimal region, using median method
	node & this_node = *(temp.cur_node);
	//tinyRow & src_row = *(temp.src_row);
	if(this_node.isFixed)
		return false;

	//Assume the average pin location is at the center

	vector<double> x;
	vector<double> y;
	int OPT_lx, OPT_rx, OPT_by, OPT_ty;

	//traverse all the nets of this node
	for(int i = 0; i < this_node.pins.size(); i++)
	{
		int netID = this_node.pins[i].pin2net;
		net & this_net = ptrckt.nets[netID];
		double x_pinloc = this_node.x_coord + 0.5 * this_node.width + this_node.pins[i].x_offset;
		double y_pinloc = this_node.y_coord + 0.5 * this_node.height + this_node.pins[i].y_offset;
		
		if( (x_pinloc <= this_net.max_X) && (x_pinloc >= this_net.min_X) )
		{	// The node is within the original bounding box
			x.push_back(this_net.min_X);
			x.push_back(this_net.max_X);
		}
		else // Recalculate the bounding box
		{
			double netMaxX = ptrckt.lx;
			double netMinX = ptrckt.rx;
			for(unsigned j = 0; j < this_net.nodeIds.size(); j++)
			{
				node & cur_node = ptrckt.nodes[ ptrckt.nets[netID].nodeIds[j] ];
				double x_pinloc = cur_node.x_coord + 0.5 * cur_node.width + this_net.x_offset[j];

				if(this_net.nodeIds[j] == this_node.ID)
					continue; // Skip this node 
					
				if(j == 0)
				{
					netMaxX = netMinX = x_pinloc;
				}
				else
				{
					netMaxX = max(netMaxX, x_pinloc);
					netMinX = min(netMinX, x_pinloc);
				}
			}

			x.push_back(netMinX);
			x.push_back(netMaxX);
		}

		if( (y_pinloc <= this_net.max_Y) && (y_pinloc >= this_net.min_Y) )
		{	// The node is within the original bounding box
			y.push_back(this_net.min_Y);
			y.push_back(this_net.max_Y);
		}
		else // Recalculate the bounding box
		{
			double netMaxY = ptrckt.by;
			double netMinY = ptrckt.ty;
			for(unsigned j = 0; j < this_net.nodeIds.size(); j++)
			{
				node & cur_node = ptrckt.nodes[ ptrckt.nets[netID].nodeIds[j] ];
				double y_pinloc = cur_node.y_coord + 0.5 * cur_node.height + this_net.y_offset[j];

				if(this_net.nodeIds[j] == this_node.ID)
					continue; // Skip this node 
					
				if(j == 0)
				{
					netMaxY = netMinY = y_pinloc;
				}
				else
				{
					netMaxY = max(netMaxY, y_pinloc);
					netMinY = min(netMinY, y_pinloc);
				}
			}

			y.push_back(netMinY);
			y.push_back(netMaxY);
		}
	}
	// Calculate the median, thus deriving the optimal region of current node
	
	int num_net = this_node.pins.size();
	double opt_lx, opt_rx, opt_by, opt_ty;
	sort(x.begin(), x.end());
	sort(y.begin(), y.end());

	if(num_net == 0)
	{
		opt_lx = opt_rx = this_node.x_coord;
		opt_by = opt_ty = this_node.y_coord;
	}
	else
	{
		opt_lx = x[num_net - 1];
		opt_rx = x[num_net];
		opt_by = y[num_net - 1];
		opt_ty = y[num_net];
	}
	// Express the optimal region in terms of the left end of the node 
	OPT_lx = opt_lx - 0.5 * this_node.width - 81 * 2;
	OPT_rx = opt_rx - 0.5 * this_node.width + 81 * 2;
	OPT_by = opt_by - 0.5 * this_node.height - 81 * 2;
	OPT_ty = opt_ty - 0.5 * this_node.height + 81 * 2;
	if(OPT_lx < ptrckt.lx) OPT_lx = ptrckt.lx;
	if(OPT_rx > ptrckt.rx) OPT_rx = ptrckt.rx - 1;
	if(OPT_by < ptrckt.by) OPT_by = ptrckt.by;
	if(OPT_ty > ptrckt.ty) OPT_ty = ptrckt.ty - 1;

	assert(OPT_lx >= ptrckt.lx);
	assert(OPT_rx <= ptrckt.rx);
	assert(OPT_by >= ptrckt.by);
	assert(OPT_ty <= ptrckt.ty);

	// Select eligible tinyRows from the optimal region
	int bottomleft_ID = xy2tinyRowID(ptrckt, OPT_lx, OPT_by);
	int topleft_ID = xy2tinyRowID(ptrckt, OPT_lx, OPT_ty);
	int bottomright_ID = xy2tinyRowID(ptrckt, OPT_rx, OPT_by);

	assert(bottomright_ID - bottomleft_ID <= x_gridNum);
	int N_horizontal = bottomright_ID - bottomleft_ID;
	int srcBinID = rowid2binID(temp.src_row->ID);
	assert(bottomleft_ID >= 0 && bottomleft_ID < 9 * numBins);
	assert(topleft_ID >= 0 && topleft_ID < 9 * numBins);
	assert(N_horizontal <= x_gridNum);
	assert(srcBinID >= 0 && srcBinID < numBins);


	for(int id = bottomleft_ID; id <= topleft_ID; id += x_gridNum)
	{
		int temp_id;
		for(temp_id = id; temp_id <= id + N_horizontal; temp_id++)
		{
			int binID = rowid2binID(temp_id);
			if(binID == srcBinID)
				continue;
			/* For each candidate tinyrow, we find its corresponding tinyrow. If the bin's too far away from the original position of the node, 
				we don't consider that tinyrow */
			if(max_distance(ptrckt, temp_id, this_node) > max_displacement)
				continue;
			if(ptrckt.tinyRows[temp_id].isValid && util_array[binID] < T2 * targUt)
			{
				temp.dest_row.push(& ptrckt.tinyRows[temp_id]);
			}
		}
	}

	if(temp.dest_row.size() != 0)
		return true;
	else
		return false;
}




